package com.jie.netty.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jie.netty.callback.ConfirmCallbackService;
import com.jie.netty.callback.ReturnCallbackService;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static com.jie.constant.IMRabbitMqKey.*;

/**
 * mq配置类
 * @Author: 杰
 * @Project :netty-communication
 * @Description:
 * @DateTime: 2023/11/15 8:24
 **/
@Configuration
public class RabbitMqConfig {
    //自定义生产者发送成功回调函数
    @Autowired
    private ReturnCallbackService returnCallbackService;
    //自定义生产者发送失败回调函数
    @Autowired
    private ConfirmCallbackService confirmCallbackService;
    //配置回调函数绑定
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setReturnCallback(returnCallbackService);
        rabbitTemplate.setConfirmCallback(confirmCallbackService);
        rabbitTemplate.setMessageConverter(messageConverter());
        rabbitTemplate.setMessageConverter(jsonMessageConverter(objectMapper()));
        return rabbitTemplate;
    }
    @Bean
    public ObjectMapper objectMapper() {
        // 这里可以进行 ObjectMapper 的配置
        return new ObjectMapper();
    }

    /**
     * 序列化
     * @param objectMapper
     * @return
     */
    public MessageConverter jsonMessageConverter(ObjectMapper objectMapper) {
        return new Jackson2JsonMessageConverter(objectMapper);
    }
    //序列化
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
    //创建单聊发送端聊天发送队列
    @Bean
    public Queue directPrivateChatQueue() {
        return QueueBuilder.durable(IM_RESULT_PRIVATE_QUEUE)
                //死信交换机声明
                .withArgument("x-dead-letter-exchange", DLX_CHAT_EXCHANGE)
                //死信消息的路由key
                .withArgument("x-dead-letter-routing-key", PRIVATE)
                //消息过期时间设置 超出时间未消费成为死信
                .withArgument("x-message-ttl", 60000)
                .build();
    }

    //创建群聊发送端聊天队列
    @Bean
    public Queue directGroupChatQueue() {
        return new Queue(IM_RESULT_GROUP_QUEUE, true);
    }
    //创建单聊接受结果队列
    @Bean
    public Queue resultPrivateChatQueue() {
        return new Queue(IM_RESULT_PRIVATE_RECEIVE_QUEUE, true);
    }
    //聊天死信队列
    @Bean
    public Queue directDlxChatQueue() {
        return new Queue(DLX_CHAT_QUEUE, true);
    }
    //创建聊天交换机
    @Bean
    public DirectExchange directChatExchange() {
        return new DirectExchange(CHAT_EXCHANGE, true, false);
    }
    @Bean
    public DirectExchange resultPrivateChatExchange() {
        return new DirectExchange(RESULT_CHAT_EXCHANGE, true, false);
    }

    //聊天死信交换机
    @Bean
    public Exchange directDlxChatExchange() {
        return ExchangeBuilder
                .topicExchange(DLX_CHAT_EXCHANGE)
                .durable(true)
                .build();
    }

    //绑定交换机与队列关系
    @Bean
    public Binding directPrivateChatBinding() {
        return BindingBuilder.bind(directPrivateChatQueue()).to(directChatExchange()).with(PRIVATE);
    }
    //绑定但单聊结果交换机
    @Bean
    public Binding resultPrivateChatBinding() {
        return BindingBuilder.bind(resultPrivateChatQueue()).to(resultPrivateChatExchange()).with(PRIVATE);
    }
    @Bean
    public Binding directGroupChatBinding() {
        return BindingBuilder.bind(directGroupChatQueue()).to(directChatExchange()).with(GROUP);
    }
    /**
     * 死信队列绑定死信交换机
     * @return
     */
    @Bean
    public Binding userDeadLetterBinding() {
        return BindingBuilder
                .bind(directDlxChatQueue())
                .to(directDlxChatExchange())
                .with(PRIVATE)
                .noargs();
    }
}
